package com.xcj.juhe.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xcj.juhe.dto.UserLoginDto;
import com.xcj.juhe.entity.Verify;
import com.xcj.juhe.mapper.test1.LoginLogMapper;
import com.xcj.juhe.mapper.test2.DeviceMapper;
import com.xcj.juhe.mapper.test2.UserMapper;
import com.xcj.juhe.service.UserService;
import com.xcj.juhe.tool.DeviceTool;
import com.xcj.juhe.tool.MyTool;
import com.xcj.juhe.tool.SignSortTool;
import com.xcj.juhe.vo.RegisterUserVO;
import com.xcj.juhe.vo.ResultVO;
import com.xcj.juhe.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xcj
 * @date 2021/4/14 18:51
 */

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    //聚合的注册接口地址
    String URL = "http://test-api.gamedachen.com/user/verify";
    //联运的注册接口地址
    String SDKAPI_URL = "http://test-sdkapi.gamedachen.com/user/regAndLogAccount/2.2";

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    @Qualifier(value = "UserMapper1")
    private com.xcj.juhe.mapper.test1.UserMapper userMapper1;

    @Autowired
    @Qualifier(value = "UserMapper2")
    private UserMapper userMapper2;

    @Autowired
    @Qualifier(value = "DeviceMapper2")
    private DeviceMapper deviceMapper2;

    @Autowired
    private LoginLogMapper loginLogMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    MyTool myTool = new MyTool();

    /**
     * 调用接口注册聚合用户
     */
    public ResultVO addUser(ArrayList<RegisterUserVO> arrayList, String appId, String appkey, Map map) {
        int success_number = 0;
        Map resultMap = new HashMap();
        ArrayList<String> list = new ArrayList();

        int number = arrayList.size();

        for (int i = 0; i < number; i++) {
            map.put("userId", arrayList.get(i).getUserId());
            map.put("userName", arrayList.get(i).getUserName());
            map.put("deviceId", arrayList.get(i).getDeviceId());

            //调用聚合校验接口
            UserVO userVO = this.callVerify(map, appkey, arrayList.get(i).getTime());
            if (userVO != null) {
                success_number++;
                list.add(userVO.getUserId());
            } else {
                success_number--;
            }
        }
        ResultVO resultVO = new ResultVO();

        if (success_number > 0) {
            resultVO.setCode(200);
            resultVO.setMsg("success");
            resultMap.put("userData", list);
            resultMap.put("successNumber", success_number);
            resultVO.setData(resultMap);
        } else {
            resultVO.setCode(100);
            resultVO.setMsg("都失败了");
        }

        return resultVO;

    }

    /**
     * 调用接口注册联运用户
     *
     * @param number
     * @return
     */
    @Override
    public ArrayList<RegisterUserVO> addAccount(int number, String dcProductId, String dcChannelId, String dcAppKey, String time) {
        long startTime = new Date().getTime();
        Map map = new HashMap();
        int sum = 0;
        ArrayList<RegisterUserVO> list = new ArrayList<>();

        for (int i = 0; i < number; i++) {
            //随机生成设备号
            String dId = new DeviceTool().makeDeviceId() + "_" + i;

            //调用生成账号名
            String name = "";
            String pwd = "";

            //循环调用生成用户名接口，直到不为空
            while (name == null || name.equals("")) {
                Map<String, String> regMap = this.getRegUserNameAndPwd();
                name = regMap.get("username");
                pwd = regMap.get("password");
            }
            map.put("deviceId", dId);
            RegisterUserVO registerUserVO = regAndLogAccount(map, name, pwd, dcProductId, dcChannelId, dcAppKey, time);
            if (registerUserVO != null) {
                list.add(registerUserVO);
                sum++;
            }
        }

        long endTime = new Date().getTime();
        System.out.println("此次处理总耗时:" + (endTime - startTime) / 1000);

        if (sum > 0) {
            return list;
        } else {
            log.error("联运，都注册失败");
            return null;
        }
    }

    /**
     * 聚合批量用户登录
     *
     * @param userLoginDto
     * @return
     */
    @Override
    public ResultVO usersLogin(UserLoginDto userLoginDto) {

        ResultVO resultVO = new ResultVO();

        String channelId = userLoginDto.getMintChannelId();
        String appKey = userLoginDto.getAppKey();
        String deviceId = userLoginDto.getDeviceId();
        ArrayList<String> subUserIds = userLoginDto.getSubUserIds();
        ArrayList<String> successNums = new ArrayList();
        for (String subUserId : subUserIds) {
            //通过小号id查询用户信息是否存在
            String userName = userMapper2.selectUserNameBySubUserId(subUserId);
            if (!userName.equals("")) {
                Verify verify = new Verify();
                verify.setChannelId(Integer.parseInt(channelId));
                verify.setSubChannelId(0);
                verify.setDeviceId(deviceId);
                verify.setUserId(subUserId);
                verify.setUserName(userName);
                verify.setExInfo("测试");
                verify.setRealUserInfo("");
                Map<String, Object> map = MyTool.beanToMap(verify);

                //调用聚合的注册校验登录的形式
                UserVO userVO = this.callVerify2(map, appKey, userLoginDto.getTime());
                if (userVO != null) {
                    successNums.add(userVO.getUserId());
                }
            }
        }

        if (successNums.size() > 0) {
            resultVO.setCode(200);
            resultVO.setMsg("该批次小号成功登录个数：" + successNums.size());
            resultVO.setData(successNums);
        } else {
            resultVO.setCode(100);
            resultVO.setMsg("都登录失败了");
        }

        return resultVO;
    }

    /**
     * 获取已注册联运小号id
     */
    @Override
    public ArrayList<String> getCanLoginSubUserIds(String dcChannelId, String dcProductId, String time) {
        String startTimeStr = "";
        String endTimeStr = "";
        if (!"".equals(time) && time != null) {
            try {
                startTimeStr = String.valueOf(myTool.getStartTime(time).getTime() / 1000);
                endTimeStr = String.valueOf(myTool.getEndTime(time).getTime() / 1000);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        ArrayList<String> canLoginSubUserIds = userMapper2.getCanLoginSubUserIds(dcChannelId, dcProductId, startTimeStr, endTimeStr);
        log.info("产品id：{},渠道id：{}  可登录小号集合：{}", dcProductId, dcChannelId, canLoginSubUserIds);

        return canLoginSubUserIds;
    }

    //调用聚合的校验接口去注册
    private UserVO callVerify(Map map, String appkey, String timeStr) {

        if (map.get("sign") != null) {
            map.remove("sign");
        }

        //生成签名
        String linkString = SignSortTool.createLinkString(map, true, false);
        String signString = linkString + appkey;
        log.info("signString:{}", signString);
        String md5Str = DigestUtils.md5DigestAsHex(signString.getBytes());

        map.put("sign", md5Str);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Map<String, Object>> request = new HttpEntity<Map<String, Object>>(map, headers);

        ResponseEntity<String> entity = restTemplate.postForEntity(URL, request, String.class);

        String body = entity.getBody();

        log.info("{}注册了，接口响应：{}", map.get("userId"), body);

        JSONObject json = JSON.parseObject(body);
        String code = json.getString("code");

        if (code.equals("200")) {

            String userId = json.getJSONObject("data").getString("userId");
            String userName = json.getJSONObject("data").getString("userName");
            if (!myTool.isNowDay2(timeStr)){
                //修改聚合用户注册时间
                int i = userMapper1.UpdateUserCreateTimeByUserId(userId, timeStr);
                int j = loginLogMapper.updateLastLoginTimeByDeviceId(map.get("deviceId").toString(), timeStr);
                if (i > 0 && j > 0) {
                    log.info("更新用户{}的注册、登录时间为{}成功。", userName, timeStr);
                    UserVO userVO = new UserVO();
                    userVO.setUserId(userId);
                    userVO.setUserName(userName);
                    return userVO;
                } else {
                    log.error("更新用户{}的注册、登录时间为{}失败！！！", userName, timeStr);
                    return null;
                }
            }else {
                UserVO userVO = new UserVO();
                userVO.setUserId(userId);
                userVO.setUserName(userName);
                log.info("用户{}的注册时间为{}，注册成功。", userName, timeStr);
                return userVO;
            }


        } else {
            log.error("登录失败:{}", body);
            return null;
        }
    }

    //调用聚合的校验接口去登录（仅更新登录时间）
    private UserVO callVerify2(Map map, String appkey, String time) {

        String timeStr = myTool.StringToTime(time);

        if (map.get("sign") != null) {
            map.remove("sign");
        }

        //生成签名
        String linkString = SignSortTool.createLinkString(map, true, false);
        String signString = linkString + appkey;
        log.info("signString:{}", signString);
        String md5Str = DigestUtils.md5DigestAsHex(signString.getBytes());

        map.put("sign", md5Str);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Map<String, Object>> request = new HttpEntity<Map<String, Object>>(map, headers);

        ResponseEntity<String> entity = restTemplate.postForEntity(URL, request, String.class);

        String body = entity.getBody();

        log.info("{}注册了，接口响应：{}", map.get("userId"), body);

        JSONObject json = JSON.parseObject(body);
        String code = json.getString("code");

        if (code.equals("200")) {

            String userId = json.getJSONObject("data").getString("userId");
            String userName = json.getJSONObject("data").getString("userName");

            if (!myTool.isNowDay2(timeStr)){
                //修改聚合用户登录时间(前提：登录时间要大于注册时间)
                if (Integer.parseInt(timeStr) > Integer.parseInt(userMapper1.selectUserRegTimeByUserId(userId))) {
                    int i = userMapper1.UpdateUserLoginTimeByUserId(userId, timeStr);
                    int j = loginLogMapper.updateLastLoginTimeByDeviceId(map.get("deviceId").toString(), timeStr);
                    if (i > 0 && j > 0) {
                        log.info("更新用户{}的注册时间为{}成功。", userName, timeStr);
                        UserVO userVO = new UserVO();
                        userVO.setUserId(userId);
                        userVO.setUserName(userName);
                        return userVO;
                    } else {
                        log.error("更新用户{}的注册时间为{}失败！！！", userName, timeStr);
                        return null;
                    }
                } else {
                    log.error("登录时间不能在注册时间之前！！！");
                    return null;
                }
            }else {
                UserVO userVO = new UserVO();
                userVO.setUserId(userId);
                userVO.setUserName(userName);
                log.info("用户{}的登录时间为{}，登录成功。", userName, timeStr);
                return userVO;
            }

        } else {
            log.error("登录失败:{}", body);
            return null;
        }
    }

    /**
     * 获取用户名
     */
    private Map<String, String> getRegUserNameAndPwd() {

        Map<String, String> map = new HashMap<>();
        //随机生成用户名地址
        String quickReg_url = "http://test-sdkapi.gamedachen.com/user/quickReg?companyId=42";
        ResponseEntity<String> entity = restTemplate.getForEntity(quickReg_url, String.class);
        String body = entity.getBody();
        JSONObject json = JSON.parseObject(body);

        String userName = json.getJSONObject("data").getString("userName");
        String passWord = json.getJSONObject("data").getString("userPassWord");
        String pwdMd5Sign = DigestUtils.md5DigestAsHex(passWord.getBytes());

        map.put("username", userName);
        map.put("password", pwdMd5Sign);
        return map;
    }

    /**
     * 新建联运账号
     */
    private RegisterUserVO regAndLogAccount(Map map, String regUserName, String regUserPwd, String dcProductId, String dcChannelId, String appKey, String time) {

        RegisterUserVO user = null;
        String timeStr = myTool.StringToTime(time);

        //调用初始化接口
        Map initMap = new HashMap();
        initMap.put("productId", dcProductId);
        initMap.put("channelId", dcChannelId);
        initMap.put("deviceModel", "注册_test");
        initMap.put("deviceId", map.get("deviceId"));
        initMap.put("osType", 1);
        if (this.init(initMap, timeStr)) {
            //新注册
            map.put("userName", regUserName);
            map.put("password", regUserPwd);
            map.put("deviceModel", "VOG-AL00");
            map.put("osVersion", "android5.1.1");
            map.put("productId", dcProductId);
            map.put("channelId", dcChannelId);
            map.put("mlChannelId", "0");
            //公司主体ID
            map.put("companyId", 42);
            //handleType  0 注册  1 登录
            map.put("handleType", 0);
            map.put("osType", "1");

            if (map.get("sign") != null) {
                map.remove("sign");
            }

            //生成签名
            String linkString = SignSortTool.createLinkString(map, true, false);
            String signString = linkString + appKey;
            log.info("signString:{}", signString);
            String md5Str = DigestUtils.md5DigestAsHex(signString.getBytes());

            map.put("sign", md5Str);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity<Map<String, Object>> request = new HttpEntity<Map<String, Object>>(map, headers);

            ResponseEntity<String> entity = restTemplate.postForEntity(SDKAPI_URL, request, String.class);

            String body = entity.getBody();
            log.info("游客注册：{}", body);

            //channelId=10000&deviceId=deviceId_35111961151620472432433&deviceModel=VOG-AL00&mlChannelId=0&osVersion=android5.1.1&password=7fa26731f542ec63b51c54b1ae8bfc72&realUserInfo=&subChannelId=0&userName=n3_c9tl9nf6364cd2631cdc28d1cccb4d220978a3292f9

            JSONObject json = JSON.parseObject(body);
            String code = json.getString("code");

            if (code.equals("200")) {

                int userId = Integer.parseInt(json.getJSONObject("data").getJSONObject("subUserResponse").getString("defaultId"));
                String userName = json.getJSONObject("data").getString("userName");
                int subUserId = json.getJSONObject("data").getJSONObject("subUserResponse").getInteger("defaultId");

                if (!myTool.isNowDay2(timeStr)){
                    int i = userMapper2.updateUserRegTimeByUserName(userName, timeStr);
                    if (i > 0) {
                        log.info("更新联运账号{}注册时间{}成功。", userName, timeStr);
                        user = new RegisterUserVO();
                        user.setUserId(userId);
                        user.setUserName(userName);
                        user.setSubUserId(subUserId);
                        user.setDeviceId(map.get("deviceId").toString());
                        user.setTime(timeStr);
                        return user;
                    } else {
                        log.error("更新联运账号{}注册时间{}失败！！！", userName, timeStr);
                    }
                }else {
                    user = new RegisterUserVO();
                    user.setUserId(userId);
                    user.setUserName(userName);
                    user.setSubUserId(subUserId);
                    user.setDeviceId(map.get("deviceId").toString());
                    user.setTime(timeStr);
                    return user;
                }
            }
        } else {
            log.error("设备初始化失败");
        }
        return null;
    }

    /**
     * 调用初始化接口
     */
    private Boolean init(Map map, String timeStr) {
        //初始化接口
        String url = "http://test-sdkapi.gamedachen.com/product/init/2.5?productId={productId}&channelId={channelId}&deviceModel={deviceModel}&deviceId={deviceId}&osType={osType}";

        ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class, map);

        String body = entity.getBody();

        JSONObject json = JSON.parseObject(body);
        String code = json.getString("code");
        if (code.equals("200")) {
            //不是当天就更新设备初始化时间
            if (!myTool.isNowDay2(timeStr)){
                int i = deviceMapper2.updateDeviceInitTimeByDeviceId(map.get("deviceId").toString(), timeStr);
                if (i > 0) {
                    log.info("初始化成功：{}", body);
                    return true;
                } else {
                    log.error("初始化更新时间失败");
                    return false;
                }
            }else {
                log.info("初始化成功：{}", body);
                return true;
            }
        } else {
            log.error("初始化失败：{}", body);
            return false;
        }
    }

}